/*
Copyright (c) [2019年5月1日] []
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "pch.h"
#include "framework.h"



#ifdef _DEBUG 

//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexDebugCUDA_x64.lib")
//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexDebugD3D_x64.lib")
//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexDeviceDebug_x64.lib")
//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexExtDebugCUDA_x64.lib")
//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexExtDebugD3D_x64.lib")


#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexDebugD3D_x64.lib")
#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexDeviceDebug_x64.lib")
#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexExtDebugD3D_x64.lib")




#else

#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexReleaseD3D_x64.lib")
#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexDeviceRelease_x64.lib")
#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexExtReleaseD3D_x64.lib")
//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexReleaseCUDA_x64.lib")
//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexDeviceRelease_x64.lib")
//#pragma comment(lib,"D:/U/DEV/FleX/lib/win64/NvFlexExtReleaseCUDA_x64.lib")

//#pragma comment(lib,"D:/U/DEV/SDL/lib/x64/SDL2.lib")


#endif

#pragma comment(lib,"D:/U/DEV/FleX/external/NvToolsExt/lib/x64/nvToolsExt64_1.lib")
#pragma comment(lib,"D:/U/DEV/FleX/external/D3D12/libs/x64/d3d12.lib")



#include "NvFleX封装.h"
 


#include <NvFlex.h>
#include <NvFlexExt.h>

#include "../core/types.h"
#include "../core/maths.h"
#include "../core/platform.h"
#include "../core/mesh.h"
#include "../core/voxelize.h"
#include "../core/sdf.h"
#include "../core/pfm.h"
#include "../core/tga.h"
#include "../core/perlin.h"
#include "../core/convex.h"
#include "../core/cloth.h"

//using namespace std;
//#include "helpers.h"


#include <vector>



static bool g_Error = false;
static bool g_profile = false;




struct SimBuffers
{
	NvFlexVector<Vec4> positions;
	NvFlexVector<Vec4> restPositions;
	NvFlexVector<Vec3> velocities;
	NvFlexVector<int32> phases;
	NvFlexVector<float32> densities;
	NvFlexVector<Vec4> anisotropy1;
	NvFlexVector<Vec4> anisotropy2;
	NvFlexVector<Vec4> anisotropy3;
	NvFlexVector<Vec4> normals;
	NvFlexVector<Vec4> smoothPositions;
	NvFlexVector<Vec4> diffusePositions;
	NvFlexVector<Vec4> diffuseVelocities;
	NvFlexVector<int32> diffuseCount;

	NvFlexVector<int32> activeIndices;

	// convexes
	NvFlexVector<NvFlexCollisionGeometry> shapeGeometry;
	NvFlexVector<Vec4> shapePositions;
	NvFlexVector<Quat> shapeRotations;
	NvFlexVector<Vec4> shapePrevPositions;
	NvFlexVector<Quat> shapePrevRotations;
	NvFlexVector<int> shapeFlags;

	// rigids
	NvFlexVector<int> rigidOffsets;
	NvFlexVector<int> rigidIndices;
	NvFlexVector<int> rigidMeshSize;
	NvFlexVector<float> rigidCoefficients;
	NvFlexVector<float> rigidPlasticThresholds;
	NvFlexVector<float> rigidPlasticCreeps;
	NvFlexVector<Quat> rigidRotations;
	NvFlexVector<Vec3> rigidTranslations;
	NvFlexVector<Vec3> rigidLocalPositions;
	NvFlexVector<Vec4> rigidLocalNormals;

	// inflatables
	NvFlexVector<int> inflatableTriOffsets;
	NvFlexVector<int> inflatableTriCounts;
	NvFlexVector<float> inflatableVolumes;
	NvFlexVector<float> inflatableCoefficients;
	NvFlexVector<float> inflatablePressures;

	// springs
	NvFlexVector<int> springIndices;
	NvFlexVector<float> springLengths;
	NvFlexVector<float> springStiffness;

	NvFlexVector<int> triangles;
	NvFlexVector<Vec3> triangleNormals;
	NvFlexVector<Vec3> uvs;

	SimBuffers(NvFlexLibrary* l) :
		positions(l), restPositions(l), velocities(l), phases(l), densities(l),
		anisotropy1(l), anisotropy2(l), anisotropy3(l), normals(l), smoothPositions(l),
		diffusePositions(l), diffuseVelocities(l), diffuseCount(l), activeIndices(l),
		shapeGeometry(l), shapePositions(l), shapeRotations(l), shapePrevPositions(l),
		shapePrevRotations(l), shapeFlags(l), rigidOffsets(l), rigidIndices(l), rigidMeshSize(l),
		rigidCoefficients(l), rigidPlasticThresholds(l), rigidPlasticCreeps(l), rigidRotations(l), rigidTranslations(l),
		rigidLocalPositions(l), rigidLocalNormals(l), inflatableTriOffsets(l),
		inflatableTriCounts(l), inflatableVolumes(l), inflatableCoefficients(l),
		inflatablePressures(l), springIndices(l), springLengths(l),
		springStiffness(l), triangles(l), triangleNormals(l), uvs(l)
	{}
};





struct Emitter
{
	Emitter() : mSpeed(0.0f), mEnabled(false), mLeftOver(0.0f), mWidth(8) {}

	Vec3 mPos;
	Vec3 mDir;
	Vec3 mRight;
	float mSpeed;
	bool mEnabled;
	float mLeftOver;
	int mWidth;
};


struct Rope
{
	std::vector<int> mIndices;
};





static const int g_numSkinWeights = 4;








void MapBuffers(SimBuffers* buffers)
{
	buffers->positions.map();
	buffers->restPositions.map();
	buffers->velocities.map();
	buffers->phases.map();
	buffers->densities.map();
	buffers->anisotropy1.map();
	buffers->anisotropy2.map();
	buffers->anisotropy3.map();
	buffers->normals.map();
	buffers->diffusePositions.map();
	buffers->diffuseVelocities.map();
	buffers->diffuseCount.map();
	buffers->smoothPositions.map();
	buffers->activeIndices.map();

	// convexes
	buffers->shapeGeometry.map();
	buffers->shapePositions.map();
	buffers->shapeRotations.map();
	buffers->shapePrevPositions.map();
	buffers->shapePrevRotations.map();
	buffers->shapeFlags.map();

	buffers->rigidOffsets.map();
	buffers->rigidIndices.map();
	buffers->rigidMeshSize.map();
	buffers->rigidCoefficients.map();
	buffers->rigidPlasticThresholds.map();
	buffers->rigidPlasticCreeps.map();
	buffers->rigidRotations.map();
	buffers->rigidTranslations.map();
	buffers->rigidLocalPositions.map();
	buffers->rigidLocalNormals.map();

	buffers->springIndices.map();
	buffers->springLengths.map();
	buffers->springStiffness.map();

	// inflatables
	buffers->inflatableTriOffsets.map();
	buffers->inflatableTriCounts.map();
	buffers->inflatableVolumes.map();
	buffers->inflatableCoefficients.map();
	buffers->inflatablePressures.map();

	buffers->triangles.map();
	buffers->triangleNormals.map();
	buffers->uvs.map();
}

void UnmapBuffers(SimBuffers* buffers)
{
	// particles
	buffers->positions.unmap();
	buffers->restPositions.unmap();
	buffers->velocities.unmap();
	buffers->phases.unmap();
	buffers->densities.unmap();
	buffers->anisotropy1.unmap();
	buffers->anisotropy2.unmap();
	buffers->anisotropy3.unmap();
	buffers->normals.unmap();
	buffers->diffusePositions.unmap();
	buffers->diffuseVelocities.unmap();
	buffers->diffuseCount.unmap();
	buffers->smoothPositions.unmap();
	buffers->activeIndices.unmap();

	// convexes
	buffers->shapeGeometry.unmap();
	buffers->shapePositions.unmap();
	buffers->shapeRotations.unmap();
	buffers->shapePrevPositions.unmap();
	buffers->shapePrevRotations.unmap();
	buffers->shapeFlags.unmap();

	// rigids
	buffers->rigidOffsets.unmap();
	buffers->rigidIndices.unmap();
	buffers->rigidMeshSize.unmap();
	buffers->rigidCoefficients.unmap();
	buffers->rigidPlasticThresholds.unmap();
	buffers->rigidPlasticCreeps.unmap();
	buffers->rigidRotations.unmap();
	buffers->rigidTranslations.unmap();
	buffers->rigidLocalPositions.unmap();
	buffers->rigidLocalNormals.unmap();

	// springs
	buffers->springIndices.unmap();
	buffers->springLengths.unmap();
	buffers->springStiffness.unmap();

	// inflatables
	buffers->inflatableTriOffsets.unmap();
	buffers->inflatableTriCounts.unmap();
	buffers->inflatableVolumes.unmap();
	buffers->inflatableCoefficients.unmap();
	buffers->inflatablePressures.unmap();

	// triangles
	buffers->triangles.unmap();
	buffers->triangleNormals.unmap();
	buffers->uvs.unmap();

}

SimBuffers* AllocBuffers(NvFlexLibrary* lib)
{
	return new SimBuffers(lib);
}

void DestroyBuffers(SimBuffers* buffers)
{
	// particles
	buffers->positions.destroy();
	buffers->restPositions.destroy();
	buffers->velocities.destroy();
	buffers->phases.destroy();
	buffers->densities.destroy();
	buffers->anisotropy1.destroy();
	buffers->anisotropy2.destroy();
	buffers->anisotropy3.destroy();
	buffers->normals.destroy();
	buffers->diffusePositions.destroy();
	buffers->diffuseVelocities.destroy();
	buffers->diffuseCount.destroy();
	buffers->smoothPositions.destroy();
	buffers->activeIndices.destroy();

	// convexes
	buffers->shapeGeometry.destroy();
	buffers->shapePositions.destroy();
	buffers->shapeRotations.destroy();
	buffers->shapePrevPositions.destroy();
	buffers->shapePrevRotations.destroy();
	buffers->shapeFlags.destroy();

	// rigids
	buffers->rigidOffsets.destroy();
	buffers->rigidIndices.destroy();
	buffers->rigidMeshSize.destroy();
	buffers->rigidCoefficients.destroy();
	buffers->rigidPlasticThresholds.destroy();
	buffers->rigidPlasticCreeps.destroy();
	buffers->rigidRotations.destroy();
	buffers->rigidTranslations.destroy();
	buffers->rigidLocalPositions.destroy();
	buffers->rigidLocalNormals.destroy();

	// springs
	buffers->springIndices.destroy();
	buffers->springLengths.destroy();
	buffers->springStiffness.destroy();

	// inflatables
	buffers->inflatableTriOffsets.destroy();
	buffers->inflatableTriCounts.destroy();
	buffers->inflatableVolumes.destroy();
	buffers->inflatableCoefficients.destroy();
	buffers->inflatablePressures.destroy();

	// triangles
	buffers->triangles.destroy();
	buffers->triangleNormals.destroy();
	buffers->uvs.destroy();

	delete buffers;
}




struct S_解算参数 {
	NvFlexSolver*		g_solver;
	NvFlexSolverDesc	g_solverDesc;
	NvFlexLibrary*		g_flexLib;
	NvFlexParams		g_params;
	NvFlexTimers		g_timers;
	int32				g_numDetailTimers;
	NvFlexDetailTimer* g_detailTimers;

	int32				g_maxDiffuseParticles;
	int32				g_maxNeighborsPerParticle;
	int32				g_numExtraParticles;
	int32				g_numExtraMultiplier = 1;
	int32				g_maxContactsPerParticle;

	Mesh* g_mesh;
	std::vector<int32>		g_meshSkinIndices;
	std::vector<float32>	g_meshSkinWeights;
	std::vector<Point3>		g_meshRestPositions;


	std::vector<Rope>		g_ropes;
	std::vector<Emitter>	g_emitters;
	

	SimBuffers*				g_buffers;

	Vec3					g_sceneLower;
	Vec3					g_sceneUpper;

	bool					g_warmup;
	bool					g_wavePool;
	float32					g_waveTime;
	float32					g_wavePlane;
	float32					g_waveFrequency;
	float32					g_waveAmplitude;
	float32					g_waveFloorTilt;
	//sim->g_emit = false;
	

	int32					g_numSolidParticles;

	int32					g_frame;
	float32					g_dt;
	float32					g_simLatency;
	int32					g_numSubsteps;
	int32					g_device;



	bool					g_shapesChanged;
	//std::map<NvFlexConvexMeshId, GpuMesh*>		g_convexes;
	//std::map<NvFlexTriangleMeshId, GpuMesh*>		g_meshes;
	//std::map<NvFlexDistanceFieldId, GpuMesh*>		g_fields;
};







void GetParticleBounds(Vec3& lower, Vec3& upper, SimBuffers* g_buffers)
{
	lower = Vec3(FLT_MAX);
	upper = Vec3(-FLT_MAX);

	for (int i = 0; i < g_buffers->positions.size(); ++i)
	{
		lower = Min(Vec3(g_buffers->positions[i]), lower);
		upper = Max(Vec3(g_buffers->positions[i]), upper);
	}
}

void GetShapeBounds(Vec3& totalLower, Vec3& totalUpper, SimBuffers* g_buffers, NvFlexLibrary* g_flexLib)
{
	Bounds totalBounds;

	for (int i = 0; i < g_buffers->shapeFlags.size(); ++i)
	{
		NvFlexCollisionGeometry geo = g_buffers->shapeGeometry[i];

		int type = g_buffers->shapeFlags[i] & eNvFlexShapeFlagTypeMask;

		Vec3 localLower;
		Vec3 localUpper;

		switch (type)
		{
		case eNvFlexShapeBox:
		{
			localLower = -Vec3(geo.box.halfExtents);
			localUpper = Vec3(geo.box.halfExtents);
			break;
		}
		case eNvFlexShapeSphere:
		{
			localLower = -geo.sphere.radius;
			localUpper = geo.sphere.radius;
			break;
		}
		case eNvFlexShapeCapsule:
		{
			localLower = -Vec3(geo.capsule.halfHeight, 0.0f, 0.0f) - Vec3(geo.capsule.radius);
			localUpper = Vec3(geo.capsule.halfHeight, 0.0f, 0.0f) + Vec3(geo.capsule.radius);
			break;
		}
		case eNvFlexShapeConvexMesh:
		{
			NvFlexGetConvexMeshBounds(g_flexLib, geo.convexMesh.mesh, localLower, localUpper);

			// apply instance scaling
			localLower *= geo.convexMesh.scale;
			localUpper *= geo.convexMesh.scale;
			break;
		}
		case eNvFlexShapeTriangleMesh:
		{
			NvFlexGetTriangleMeshBounds(g_flexLib, geo.triMesh.mesh, localLower, localUpper);

			// apply instance scaling
			localLower *= Vec3(geo.triMesh.scale);
			localUpper *= Vec3(geo.triMesh.scale);
			break;
		}
		case eNvFlexShapeSDF:
		{
			localLower = 0.0f;
			localUpper = geo.sdf.scale;
			break;
		}
		};

		// transform local bounds to world space
		Vec3 worldLower, worldUpper;
		TransformBounds(localLower, localUpper, Vec3(g_buffers->shapePositions[i]), g_buffers->shapeRotations[i], 1.0f, worldLower, worldUpper);

		totalBounds = Union(totalBounds, Bounds(worldLower, worldUpper));
	}

	totalLower = totalBounds.lower;
	totalUpper = totalBounds.upper;
}

void ErrorCallback(NvFlexErrorSeverity severity, const char* msg, const char* file, int line)
{
	printf("Flex: %s - %s:%d\n", msg, file, line);
	g_Error = (severity == eNvFlexLogError);
	//assert(0); asserts are bad for TeamCity
}

void CalculateRigidCentersOfMass(const Vec4* restPositions, int numRestPositions, const int* offsets, Vec3* translations, const int* indices, int numRigids)
{
	// To improve the accuracy of the result, first transform the restPositions to relative coordinates (by finding the mean and subtracting that from all positions)
	// Note: If this is not done, one might see ghost forces if the mean of the restPositions is far from the origin.
	Vec3 shapeOffset(0.0f);

	for (int i = 0; i < numRestPositions; i++) {
		shapeOffset += Vec3(restPositions[i]);
	}

	shapeOffset /= float(numRestPositions);
	for (int i = 0; i < numRigids; ++i) {
		const int startIndex = offsets[i];
		const int endIndex = offsets[i + 1];
		const int n = endIndex - startIndex;
		assert(n);
		Vec3 com;

		for (int j = startIndex; j < endIndex; ++j) {
			const int r = indices[j];
			// By subtracting shapeOffset the calculation is done in relative coordinates
			com += Vec3(restPositions[r]) - shapeOffset;
		}
		com /= float(n);
		// Add the shapeOffset to switch back to absolute coordinates
		com += shapeOffset;
		translations[i] = com;
	}
}

void CalculateRigidLocalPositions(const Vec4* restPositions, const int* offsets, const Vec3* translations, const int* indices, int numRigids, Vec3* localPositions)
{
	int count = 0;
	for (int i = 0; i < numRigids; ++i) {
		const int startIndex = offsets[i];
		const int endIndex = offsets[i + 1];

		assert(endIndex - startIndex);
		for (int j = startIndex; j < endIndex; ++j) {
			const int r = indices[j];
			localPositions[count++] = Vec3(restPositions[r]) - translations[i];
		}
	}
}




















static std::set<S_解算参数*> g_解算器;






uint64 f_NvFlex_初始化参数(uint32 设备) {
	S_解算参数* sim = new S_解算参数;
	g_解算器.insert(sim);

	sim->g_solver = nullptr;
	sim->g_flexLib = nullptr;
	sim->g_mesh = nullptr;
	sim->g_buffers = nullptr;

	NvFlexInitDesc desc;
	desc.deviceIndex = 设备;
	desc.enableExtensions = true;
	desc.renderDevice = 0;
	desc.renderContext = 0;
	desc.computeContext = 0;
	//desc.computeType = eNvFlexCUDA;
	//desc.computeType = eNvFlexD3D12;
	desc.computeType = eNvFlexD3D11;
	sim->g_flexLib = NvFlexInit(NV_FLEX_VERSION, ErrorCallback, &desc);
	

	sim->g_shapesChanged = true;

	return (uint64)sim;
}

void f_NvFlex_释放(uint64 key)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;
	
	NvFlexShutdown(sim->g_flexLib);
}

void f_NvFleX_重置begin(uint64 key, uint32 飞溅粒子数量, bool 重置大小) {
	RandInit();

	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;
	

	

	/*for (auto& iter : g_meshes) {
			NvFlexDestroyTriangleMesh(g_flexLib, iter.first);
			DestroyGpuMesh(iter.second);
		}
		for (auto& iter : g_fields)
		{
			NvFlexDestroyDistanceField(g_flexLib, iter.first);
			DestroyGpuMesh(iter.second);
		}
		for (auto& iter : g_convexes)
		{
			NvFlexDestroyConvexMesh(g_flexLib, iter.first);
			DestroyGpuMesh(iter.second);
		}
		g_fields.clear();
		g_meshes.clear();
		g_convexes.clear();*/
	if (!sim->g_buffers) return;

	if (重置大小) {
		if (sim->g_solver) {
			if (sim->g_buffers) DestroyBuffers(sim->g_buffers);
			NvFlexDestroySolver(sim->g_solver);
			sim->g_solver = NULL;
		}
		// alloc buffers
		sim->g_buffers = AllocBuffers(sim->g_flexLib);
	}
	else {
		MapBuffers(sim->g_buffers);
		return;
	}
	

	// map during initialization
	MapBuffers(sim->g_buffers);

	sim->g_buffers->positions.resize(0);
	sim->g_buffers->velocities.resize(0);
	sim->g_buffers->phases.resize(0);

	sim->g_buffers->rigidOffsets.resize(0);
	sim->g_buffers->rigidIndices.resize(0);
	sim->g_buffers->rigidMeshSize.resize(0);
	sim->g_buffers->rigidRotations.resize(0);
	sim->g_buffers->rigidTranslations.resize(0);
	sim->g_buffers->rigidCoefficients.resize(0);
	sim->g_buffers->rigidPlasticThresholds.resize(0);
	sim->g_buffers->rigidPlasticCreeps.resize(0);
	sim->g_buffers->rigidLocalPositions.resize(0);
	sim->g_buffers->rigidLocalNormals.resize(0);

	sim->g_buffers->springIndices.resize(0);
	sim->g_buffers->springLengths.resize(0);
	sim->g_buffers->springStiffness.resize(0);
	sim->g_buffers->triangles.resize(0);
	sim->g_buffers->triangleNormals.resize(0);
	sim->g_buffers->uvs.resize(0);

	sim->g_meshSkinIndices.resize(0);
	sim->g_meshSkinWeights.resize(0);

	sim->g_emitters.resize(1);
	sim->g_emitters[0].mEnabled = false;
	sim->g_emitters[0].mSpeed = 1.0f;
	sim->g_emitters[0].mLeftOver = 0.0f;
	sim->g_emitters[0].mWidth = 8;

	sim->g_buffers->shapeGeometry.resize(0);
	sim->g_buffers->shapePositions.resize(0);
	sim->g_buffers->shapeRotations.resize(0);
	sim->g_buffers->shapePrevPositions.resize(0);
	sim->g_buffers->shapePrevRotations.resize(0);
	sim->g_buffers->shapeFlags.resize(0);

	sim->g_ropes.resize(0);

	// remove collision shapes
	delete sim->g_mesh; sim->g_mesh = NULL;

	sim->g_frame = 0;
	sim->g_dt = 1.0f / 60.0f;

	// sim params
	sim->g_params.gravity[0] = 0.0f;
	sim->g_params.gravity[1] = -9.8f;
	sim->g_params.gravity[2] = 0.0f;

	sim->g_params.wind[0] = 0.0f;
	sim->g_params.wind[1] = 0.0f;
	sim->g_params.wind[2] = 0.0f;

	sim->g_params.radius = 0.05f;
	sim->g_params.viscosity = 0.0f;
	sim->g_params.dynamicFriction = 0.0f;
	sim->g_params.staticFriction = 0.0f;
	sim->g_params.particleFriction = 0.0f; // scale friction between particles by default
	sim->g_params.freeSurfaceDrag = 0.0f;
	sim->g_params.drag = 0.0f;
	sim->g_params.lift = 0.0f;
	sim->g_params.numIterations = 3;
	sim->g_params.fluidRestDistance = 0.0f;
	sim->g_params.solidRestDistance = 0.0f;

	sim->g_params.anisotropyScale = 1.0f;
	sim->g_params.anisotropyMin = 0.1f;
	sim->g_params.anisotropyMax = 2.0f;
	sim->g_params.smoothing = 1.0f;

	sim->g_params.dissipation = 0.0f;
	sim->g_params.damping = 0.0f;
	sim->g_params.particleCollisionMargin = sim->g_params.radius * 0.05;
	sim->g_params.shapeCollisionMargin = 0.0f;
	sim->g_params.collisionDistance = 0.0f;
	sim->g_params.sleepThreshold = 0.0f;
	sim->g_params.shockPropagation = 0.0f;
	sim->g_params.restitution = 0.0f;

	sim->g_params.maxSpeed = FLT_MAX;
	sim->g_params.maxAcceleration = 100.0f;	// approximately 10x gravity

	sim->g_params.relaxationMode = eNvFlexRelaxationLocal;
	sim->g_params.relaxationFactor = 1.0f;
	sim->g_params.solidPressure = 1.0f;
	sim->g_params.adhesion = 0.0f;
	sim->g_params.cohesion = 0.025f;
	sim->g_params.surfaceTension = 0.0f;
	sim->g_params.vorticityConfinement = 0.0f;
	sim->g_params.buoyancy = 1.0f;
	sim->g_params.diffuseThreshold = 100.0f;
	sim->g_params.diffuseBuoyancy = 1.0f;
	sim->g_params.diffuseDrag = 0.8f;
	sim->g_params.diffuseBallistic = 16;
	sim->g_params.diffuseLifetime = 2.0f;

	sim->g_numSubsteps = 2;

	// planes created after particles
	sim->g_params.numPlanes = 6;



	sim->g_numSolidParticles = 0;


	sim->g_maxDiffuseParticles = 0;	// number of diffuse particles
	sim->g_maxNeighborsPerParticle = 96;
	sim->g_numExtraParticles = 0;	// number of particles allocated but not made active	
	sim->g_maxContactsPerParticle = 6;

	sim->g_sceneLower = FLT_MAX;
	sim->g_sceneUpper = -FLT_MAX;

	sim->g_wavePool = false;
	sim->g_waveTime = 0.0f;
	sim->g_wavePlane;
	sim->g_waveFrequency = 1.5f;
	sim->g_waveAmplitude = 1.0f;
	sim->g_waveFloorTilt = 0.0f;

	sim->g_waveFrequency = 1.5f;
	sim->g_waveAmplitude = 1.5f;
	//sim->g_emit = false;
	sim->g_warmup = false;
	// initialize solver desc
	NvFlexSetSolverDescDefaults(&sim->g_solverDesc);
	//UnmapBuffers(sim->g_buffers);

	
	sim->g_maxDiffuseParticles = 飞溅粒子数量;
	sim->g_buffers->diffusePositions.resize(sim->g_maxDiffuseParticles);
	sim->g_buffers->diffuseVelocities.resize(sim->g_maxDiffuseParticles);
	sim->g_buffers->diffuseCount.resize(1, 0);

}


void f_NvFleX_重置end(uint64 key, bool 重置大小)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) {
		sim = *iter;
	}
	else {
		return;
	}

	if (!sim->g_buffers) return;


	uint32_t numParticles = sim->g_buffers->positions.size();
	uint32_t maxParticles = numParticles + sim->g_numExtraParticles * sim->g_numExtraMultiplier;


	
	
	if (maxParticles <= 0 || !重置大小) {
		for (int i = 0; i < sim->g_buffers->positions.size(); ++i)
			sim->g_buffers->restPositions[i] = sim->g_buffers->positions[i];


		UnmapBuffers(sim->g_buffers);
		return;
	}

	





	if (sim->g_params.solidRestDistance == 0.0f) sim->g_params.solidRestDistance = sim->g_params.radius;
	// if fluid present then we assume solid particles have the same radius
	if (sim->g_params.fluidRestDistance > 0.0f) sim->g_params.solidRestDistance = sim->g_params.fluidRestDistance;
	// set collision distance automatically based on rest distance if not alraedy set
	if (sim->g_params.collisionDistance == 0.0f)
		sim->g_params.collisionDistance = Max(sim->g_params.solidRestDistance, sim->g_params.fluidRestDistance) * 0.5f;
	// default particle friction to 10% of shape friction
	if (sim->g_params.particleFriction == 0.0f)
		sim->g_params.particleFriction = sim->g_params.dynamicFriction * 0.1f;
	// add a margin for detecting contacts between particles and shapes
	if (sim->g_params.shapeCollisionMargin == 0.0f)
		sim->g_params.shapeCollisionMargin = sim->g_params.collisionDistance * 0.5f;

	// calculate particle bounds
	Vec3 particleLower, particleUpper;
	GetParticleBounds(particleLower, particleUpper, sim->g_buffers);

	// accommodate shapes
	Vec3 shapeLower, shapeUpper;
	GetShapeBounds(shapeLower, shapeUpper, sim->g_buffers, sim->g_flexLib);

	// update bounds
	sim->g_sceneLower = Min(Min(sim->g_sceneLower, particleLower), shapeLower);
	sim->g_sceneUpper = Max(Max(sim->g_sceneUpper, particleUpper), shapeUpper);

	sim->g_sceneLower -= sim->g_params.collisionDistance;
	sim->g_sceneUpper += sim->g_params.collisionDistance;

	// update collision planes to match flexs
	Vec3 up = Normalize(Vec3(-sim->g_waveFloorTilt, 1.0f, 0.0f));

	(Vec4&)sim->g_params.planes[0] = Vec4(up.x, up.y, up.z, 0.0f);
	(Vec4&)sim->g_params.planes[1] = Vec4(0.0f, 0.0f, 1.0f, -sim->g_sceneLower.z);
	(Vec4&)sim->g_params.planes[2] = Vec4(1.0f, 0.0f, 0.0f, -sim->g_sceneLower.x);
	(Vec4&)sim->g_params.planes[3] = Vec4(-1.0f, 0.0f, 0.0f, sim->g_sceneUpper.x);
	(Vec4&)sim->g_params.planes[4] = Vec4(0.0f, 0.0f, -1.0f, sim->g_sceneUpper.z);
	(Vec4&)sim->g_params.planes[5] = Vec4(0.0f, -1.0f, 0.0f, sim->g_sceneUpper.y);

	sim->g_wavePlane = sim->g_params.planes[2][3];

	

	// for fluid rendering these are the Laplacian smoothed positions
	sim->g_buffers->smoothPositions.resize(maxParticles);

	sim->g_buffers->normals.resize(0);
	sim->g_buffers->normals.resize(maxParticles);

	// initialize normals (just for rendering before simulation starts)
	int numTris = sim->g_buffers->triangles.size() / 3;
	for (int i = 0; i < numTris; ++i)
	{
		Vec3 v0 = Vec3(sim->g_buffers->positions[sim->g_buffers->triangles[i * 3 + 0]]);
		Vec3 v1 = Vec3(sim->g_buffers->positions[sim->g_buffers->triangles[i * 3 + 1]]);
		Vec3 v2 = Vec3(sim->g_buffers->positions[sim->g_buffers->triangles[i * 3 + 2]]);

		Vec3 n = Cross(v1 - v0, v2 - v0);

		sim->g_buffers->normals[sim->g_buffers->triangles[i * 3 + 0]] += Vec4(n, 0.0f);
		sim->g_buffers->normals[sim->g_buffers->triangles[i * 3 + 1]] += Vec4(n, 0.0f);
		sim->g_buffers->normals[sim->g_buffers->triangles[i * 3 + 2]] += Vec4(n, 0.0f);
	}

	for (int i = 0; i < int(maxParticles); ++i)
		sim->g_buffers->normals[i] = Vec4(SafeNormalize(Vec3(sim->g_buffers->normals[i]), Vec3(0.0f, 1.0f, 0.0f)), 0.0f);


	// save mesh positions for skinning
	/*if (g_mesh)
	{
		g_meshRestPositions = g_mesh->m_positions;
	}
	else
	{
		g_meshRestPositions.resize(0);
	}*/

	sim->g_solverDesc.maxParticles = maxParticles;
	sim->g_solverDesc.maxDiffuseParticles = sim->g_maxDiffuseParticles;
	sim->g_solverDesc.maxNeighborsPerParticle = sim->g_maxNeighborsPerParticle;
	sim->g_solverDesc.maxContactsPerParticle = sim->g_maxContactsPerParticle;

	// main create method for the Flex solver
	sim->g_solver = NvFlexCreateSolver(sim->g_flexLib, &sim->g_solverDesc);





	// create active indices (just a contiguous block for the demo)
	//sim->g_buffers->activeIndices.resize(sim->g_buffers->positions.size());
	//for (int i = 0; i < sim->g_buffers->activeIndices.size(); ++i)
	//	sim->g_buffers->activeIndices[i] = i;

	// resize particle buffers to fit
	sim->g_buffers->positions.resize(maxParticles);
	sim->g_buffers->velocities.resize(maxParticles);
	sim->g_buffers->phases.resize(maxParticles);

	sim->g_buffers->densities.resize(maxParticles);
	sim->g_buffers->anisotropy1.resize(maxParticles);
	sim->g_buffers->anisotropy2.resize(maxParticles);
	sim->g_buffers->anisotropy3.resize(maxParticles);

	// save rest positions
	sim->g_buffers->restPositions.resize(sim->g_buffers->positions.size());
	for (int i = 0; i < sim->g_buffers->positions.size(); ++i)
		sim->g_buffers->restPositions[i] = sim->g_buffers->positions[i];

	// builds rigids constraints
	if (sim->g_buffers->rigidOffsets.size())
	{
		assert(sim->g_buffers->rigidOffsets.size() > 1);

		const int numRigids = sim->g_buffers->rigidOffsets.size() - 1;

		// If the centers of mass for the rigids are not yet computed, this is done here
		// (If the CreateParticleShape method is used instead of the NvFlexExt methods, the centers of mass will be calculated here)
		if (sim->g_buffers->rigidTranslations.size() == 0)
		{
			sim->g_buffers->rigidTranslations.resize(sim->g_buffers->rigidOffsets.size() - 1, Vec3());
			CalculateRigidCentersOfMass(
				&sim->g_buffers->positions[0],
				sim->g_buffers->positions.size(),
				&sim->g_buffers->rigidOffsets[0],
				&sim->g_buffers->rigidTranslations[0],
				&sim->g_buffers->rigidIndices[0],
				numRigids);
		}

		// calculate local rest space positions
		sim->g_buffers->rigidLocalPositions.resize(sim->g_buffers->rigidOffsets.back());
		CalculateRigidLocalPositions(
			&sim->g_buffers->positions[0],
			&sim->g_buffers->rigidOffsets[0],
			&sim->g_buffers->rigidTranslations[0],
			&sim->g_buffers->rigidIndices[0],
			numRigids,
			&sim->g_buffers->rigidLocalPositions[0]);

		// set rigidRotations to correct length, probably NULL up until here
		sim->g_buffers->rigidRotations.resize(sim->g_buffers->rigidOffsets.size() - 1, Quat());
	}

	// unmap so we can start transferring data to GPU
	UnmapBuffers(sim->g_buffers);

	//-----------------------------
	// Send data to Flex

	NvFlexCopyDesc copyDesc;
	copyDesc.dstOffset = 0;
	copyDesc.srcOffset = 0;
	copyDesc.elementCount = numParticles;

	NvFlexSetParams(sim->g_solver, &sim->g_params);
	NvFlexSetParticles(sim->g_solver, sim->g_buffers->positions.buffer, &copyDesc);
	NvFlexSetVelocities(sim->g_solver, sim->g_buffers->velocities.buffer, &copyDesc);
	NvFlexSetNormals(sim->g_solver, sim->g_buffers->normals.buffer, &copyDesc);
	NvFlexSetPhases(sim->g_solver, sim->g_buffers->phases.buffer, &copyDesc);
	NvFlexSetRestParticles(sim->g_solver, sim->g_buffers->restPositions.buffer, &copyDesc);

	NvFlexSetActive(sim->g_solver, sim->g_buffers->activeIndices.buffer, &copyDesc);
	NvFlexSetActiveCount(sim->g_solver, sim->g_buffers->activeIndices.size());

	// springs
	if (sim->g_buffers->springIndices.size()) {
		assert((sim->g_buffers->springIndices.size() & 1) == 0);
		assert((sim->g_buffers->springIndices.size() / 2) == sim->g_buffers->springLengths.size());

		NvFlexSetSprings(sim->g_solver, sim->g_buffers->springIndices.buffer, sim->g_buffers->springLengths.buffer, sim->g_buffers->springStiffness.buffer, sim->g_buffers->springLengths.size());
	}

	// rigids
	if (sim->g_buffers->rigidOffsets.size()) {
		NvFlexSetRigids(sim->g_solver,
			sim->g_buffers->rigidOffsets.buffer,
			sim->g_buffers->rigidIndices.buffer,
			sim->g_buffers->rigidLocalPositions.buffer,
			sim->g_buffers->rigidLocalNormals.buffer,
			sim->g_buffers->rigidCoefficients.buffer,
			sim->g_buffers->rigidPlasticThresholds.buffer,
			sim->g_buffers->rigidPlasticCreeps.buffer,
			sim->g_buffers->rigidRotations.buffer,
			sim->g_buffers->rigidTranslations.buffer,
			sim->g_buffers->rigidOffsets.size() - 1,
			sim->g_buffers->rigidIndices.size());
	}

	// inflatables
	if (sim->g_buffers->inflatableTriOffsets.size()) {
		NvFlexSetInflatables(sim->g_solver,
			sim->g_buffers->inflatableTriOffsets.buffer,
			sim->g_buffers->inflatableTriCounts.buffer,
			sim->g_buffers->inflatableVolumes.buffer,
			sim->g_buffers->inflatablePressures.buffer,
			sim->g_buffers->inflatableCoefficients.buffer,
			sim->g_buffers->inflatableTriOffsets.size());
	}

	// dynamic triangles
	if (sim->g_buffers->triangles.size()) {
		NvFlexSetDynamicTriangles(sim->g_solver, sim->g_buffers->triangles.buffer, sim->g_buffers->triangleNormals.buffer, sim->g_buffers->triangles.size() / 3);
	}

	// collision shapes
	if (sim->g_buffers->shapeFlags.size())
	{
		NvFlexSetShapes(
			sim->g_solver,
			sim->g_buffers->shapeGeometry.buffer,
			sim->g_buffers->shapePositions.buffer,
			sim->g_buffers->shapeRotations.buffer,
			sim->g_buffers->shapePrevPositions.buffer,
			sim->g_buffers->shapePrevRotations.buffer,
			sim->g_buffers->shapeFlags.buffer,
			int(sim->g_buffers->shapeFlags.size()));
	}


	// perform initial sim warm up
	if (sim->g_warmup)
	{
		printf("Warming up sim..\n");

		// warm it up (relax positions to reach rest density without affecting velocity)
		NvFlexParams copy = sim->g_params;
		copy.numIterations = 4;

		NvFlexSetParams(sim->g_solver, &copy);

		const int kWarmupIterations = 100;

		for (int i = 0; i < kWarmupIterations; ++i)
		{
			NvFlexUpdateSolver(sim->g_solver, 0.0001f, 1, false);
			NvFlexSetVelocities(sim->g_solver, sim->g_buffers->velocities.buffer, NULL);
		}

		// udpate host copy
		NvFlexGetParticles(sim->g_solver, sim->g_buffers->positions.buffer, NULL);
		NvFlexGetSmoothParticles(sim->g_solver, sim->g_buffers->smoothPositions.buffer, NULL);
		NvFlexGetAnisotropy(sim->g_solver, sim->g_buffers->anisotropy1.buffer, sim->g_buffers->anisotropy2.buffer, sim->g_buffers->anisotropy3.buffer, NULL);

		printf("Finished warm up.\n");
	}


}


float32 f_NvFleX_更新(uint64 key, S_FlexParams& Params)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return 0;

	if (sim->g_solver == nullptr) return 0;

	
	sim->g_params.wind[0] = Params.wind.x;
	sim->g_params.wind[1] = Params.wind.y;
	sim->g_params.wind[2] = Params.wind.z;
	sim->g_params.drag = Params.drag;
	sim->g_params.lift = Params.lift;
	sim->g_params.gravity[0] = Params.gravity.x;
	sim->g_params.gravity[1] = Params.gravity.y;
	sim->g_params.gravity[2] = Params.gravity.z;
	sim->g_params.radius = Params.radius;
	sim->g_params.solidRestDistance = Params.solidRestDistance;
	sim->g_params.fluidRestDistance = Params.fluidRestDistance;
	sim->g_params.dynamicFriction = Params.dynamicFriction;
	sim->g_params.staticFriction = Params.staticFriction;
	sim->g_params.particleFriction = Params.particleFriction;
	sim->g_params.restitution = Params.restitution;
	sim->g_params.adhesion = Params.adhesion;
	sim->g_params.sleepThreshold = Params.sleepThreshold;
	sim->g_params.maxSpeed = Params.maxSpeed;
	sim->g_params.maxAcceleration = Params.maxAcceleration;
	sim->g_params.shockPropagation = Params.shockPropagation;
	sim->g_params.dissipation = Params.dissipation;
	sim->g_params.damping = Params.damping;
	sim->g_params.cohesion = Params.cohesion;
	sim->g_params.surfaceTension = Params.surfaceTension;
	sim->g_params.viscosity = Params.viscosity;
	sim->g_params.vorticityConfinement = Params.vorticityConfinement;
	sim->g_params.anisotropyScale = Params.anisotropyScale;
	sim->g_params.anisotropyMin = Params.anisotropyMin;
	sim->g_params.anisotropyMax = Params.anisotropyMax;
	sim->g_params.smoothing = Params.smoothing;
	sim->g_params.solidPressure = Params.solidPressure;
	sim->g_params.freeSurfaceDrag = Params.freeSurfaceDrag;
	sim->g_params.buoyancy = Params.buoyancy;
	sim->g_params.diffuseThreshold = Params.diffuseThreshold;
	sim->g_params.diffuseBuoyancy = Params.diffuseBuoyancy;
	sim->g_params.diffuseDrag = Params.diffuseDrag;
	sim->g_params.diffuseBallistic = Params.diffuseBallistic;
	sim->g_params.diffuseLifetime = Params.diffuseLifetime;
	sim->g_params.numIterations = Params.numIterations;

	sim->g_params.collisionDistance = Params.collisionDistance;
	sim->g_params.particleCollisionMargin = Params.particleCollisionMargin;
	sim->g_params.shapeCollisionMargin = Params.shapeCollisionMargin;
	
	(Vec4&)sim->g_params.planes[0] = Vec4(0, 1, 0, -Params.planes[0].y);
	(Vec4&)sim->g_params.planes[1] = Vec4(0, 0, 1, -Params.planes[0].z);
	(Vec4&)sim->g_params.planes[2] = Vec4(1, 0, 0, -Params.planes[0].x);
	(Vec4&)sim->g_params.planes[3] = Vec4(-1, 0, 0, Params.planes[1].x);
	(Vec4&)sim->g_params.planes[4] = Vec4(0, 0, -1, Params.planes[1].z);
	(Vec4&)sim->g_params.planes[5] = Vec4(0, -1, 0, Params.planes[1].y);
	/*sim->g_params.planes[0][3] = -Params.planes[0].y;
	sim->g_params.planes[1][3] = -Params.planes[0].z;
	sim->g_params.planes[2][3] = -Params.planes[0].x;
	sim->g_params.planes[3][3] = Params.planes[1].x;
	sim->g_params.planes[4][3] = Params.planes[1].z;
	sim->g_params.planes[5][3] = Params.planes[1].y;*/
	NvFlexSetParticles(sim->g_solver, sim->g_buffers->positions.buffer, NULL);
	NvFlexSetVelocities(sim->g_solver, sim->g_buffers->velocities.buffer, NULL);
	NvFlexSetPhases(sim->g_solver, sim->g_buffers->phases.buffer, NULL);
	NvFlexSetActive(sim->g_solver, sim->g_buffers->activeIndices.buffer, NULL);
	NvFlexSetActiveCount(sim->g_solver, sim->g_buffers->activeIndices.size());


	if (sim->g_shapesChanged)
	{
		NvFlexSetShapes(
			sim->g_solver,
			sim->g_buffers->shapeGeometry.buffer,
			sim->g_buffers->shapePositions.buffer,
			sim->g_buffers->shapeRotations.buffer,
			sim->g_buffers->shapePrevPositions.buffer,
			sim->g_buffers->shapePrevRotations.buffer,
			sim->g_buffers->shapeFlags.buffer,
			int(sim->g_buffers->shapeFlags.size()));

		sim->g_shapesChanged = false;
	}



	NvFlexSetParams(sim->g_solver, &sim->g_params);
	NvFlexUpdateSolver(sim->g_solver, sim->g_dt, sim->g_numSubsteps, g_profile);
	//NvFlexComputeWaitForGraphics(sim->g_flexLib);

	NvFlexGetParticles(sim->g_solver, sim->g_buffers->positions.buffer, NULL);
	NvFlexGetVelocities(sim->g_solver, sim->g_buffers->velocities.buffer, NULL);
	NvFlexGetNormals(sim->g_solver, sim->g_buffers->normals.buffer, NULL);




	// readback triangle normals
	if (sim->g_buffers->triangles.size())
		NvFlexGetDynamicTriangles(sim->g_solver, sim->g_buffers->triangles.buffer, sim->g_buffers->triangleNormals.buffer, sim->g_buffers->triangles.size() / 3);

	// readback rigid transforms
	if (sim->g_buffers->rigidOffsets.size())
		NvFlexGetRigids(sim->g_solver, NULL, NULL, NULL, NULL, NULL, NULL, NULL, sim->g_buffers->rigidRotations.buffer, sim->g_buffers->rigidTranslations.buffer);

	/*if (!g_interop)
	{
		// if not using interop then we read back fluid data to host
		if (g_drawEllipsoids)
		{
			NvFlexGetSmoothParticles(g_solver, g_buffers->smoothPositions.buffer, NULL);
			NvFlexGetAnisotropy(g_solver, g_buffers->anisotropy1.buffer, g_buffers->anisotropy2.buffer, g_buffers->anisotropy3.buffer, NULL);
		}

		// read back diffuse data to host
		if (g_drawDensity)
			NvFlexGetDensities(g_solver, g_buffers->densities.buffer, NULL);

		if (GetNumDiffuseRenderParticles(g_diffuseRenderBuffers))
		{
			NvFlexGetDiffuseParticles(g_solver, g_buffers->diffusePositions.buffer, g_buffers->diffuseVelocities.buffer, g_buffers->diffuseCount.buffer);
		}
	}
	else
	{
		// read back just the new diffuse particle count, render buffers will be updated during rendering
		NvFlexGetDiffuseParticles(g_solver, NULL, NULL, g_buffers->diffuseCount.buffer);
	}*/

	return float32();
}

static Inline uvec2 f_基本粒子拷贝(S_解算参数* sim, vec3* point, float32* 质量, float32 速度, int32 phases, uint32 num, float32 抖动, bool 是否激活) {
	uvec2 区间;
	区间.x = sim->g_buffers->positions.size();

	for (uint32 i = 0; i < num; ++i) {
		Vec3 position = Vec3(point[i].x, point[i].y, point[i].z) + RandomUnitVector() * 抖动;

		sim->g_buffers->positions.push_back(Vec4(position.x, position.y, position.z, 质量[i]));
		sim->g_buffers->velocities.push_back(速度);
		sim->g_buffers->phases.push_back(phases);

		if(是否激活) sim->g_buffers->activeIndices.push_back(区间.x + i);
	}

	区间.y = sim->g_buffers->positions.size();
	return 区间;
}

static Inline void f_基本粒子拷贝(S_解算参数* sim, vec3* point, float32* 质量, float32 速度, int32 phases, uvec2 区间, float32 抖动, bool 是否激活) {
	auto prt_pos = sim->g_buffers->positions.mappedPtr;
	auto prt_vel = sim->g_buffers->velocities.mappedPtr;
	auto prt_pha = sim->g_buffers->phases.mappedPtr;
	auto prt_act = sim->g_buffers->activeIndices.mappedPtr;

	sim->g_buffers->positions.size();
	uint32 offset = 0;
	区间.y += 区间.x;
	for (uint32 i = 区间.x; i < 区间.y; ++i, ++offset) {
		Vec3 position = Vec3(point[offset].x, point[offset].y, point[offset].z) + RandomUnitVector() * 抖动;

		prt_pos[i] = (Vec4(position.x, position.y, position.z, 质量[offset]));
		prt_vel[i] = (速度);
		prt_pha[i] = (NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid));

		if (是否激活) prt_act[i] = i;
	}
}



uvec2 f_NvFleX_添加流体(uint64 key, vec3* point, float32* 质量, float32 速度, uint32 num, bool 是否激活, float32 抖动)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return {};

	uvec2 区间;
	区间.x = sim->g_buffers->positions.size();

	for (uint32 i = 0; i < num; ++i) {
		Vec3 position = Vec3(point[i].x, point[i].y, point[i].z) + RandomUnitVector() * 抖动;

		sim->g_buffers->positions.push_back(Vec4(position.x, position.y, position.z, 质量[i]));
		sim->g_buffers->velocities.push_back(速度);
		sim->g_buffers->phases.push_back(NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid));

		if(是否激活) sim->g_buffers->activeIndices.push_back(区间.x + i);
	}
	
	sim->g_params.radius = 0.1;
	sim->g_params.dynamicFriction = 0.01f;
	sim->g_params.viscosity = 2.0f;
	sim->g_params.numIterations = 4;
	sim->g_params.vorticityConfinement = 40.0f;
	sim->g_params.fluidRestDistance = 0.1 * 0.55;
	sim->g_params.solidPressure = 0.f;
	sim->g_params.relaxationFactor = 0.0f;
	sim->g_params.cohesion = 0.02f;
	sim->g_params.collisionDistance = 0.01f;

	区间.y = sim->g_buffers->positions.size();
	return 区间;
}

uvec2 f_NvFleX_添加刚体(uint64 key, vec3* point, float32* 质量, vec4* 法线, float32 速度, uint32 num, uint32 ID, float32 刚性, float32 抖动) {
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return {};

	if(sim->g_buffers->rigidIndices.empty()) sim->g_buffers->rigidOffsets.push_back(0);
	uvec2 区间 = f_基本粒子拷贝(sim, point, 质量, 速度, NvFlexMakePhase(ID, 0), num, 抖动, true);
	
	for (uint32 i = 0; i < num; ++i) {
		sim->g_buffers->rigidIndices.push_back(区间.x + i);
		sim->g_buffers->rigidLocalNormals.push_back(Vec4(法线[i].x, 法线[i].y, 法线[i].z, 法线[i].w));
	}

	sim->g_buffers->rigidCoefficients.push_back(刚性);
	sim->g_buffers->rigidOffsets.push_back(int(sim->g_buffers->rigidIndices.size()));
	return 区间;
}

uvec2 f_NvFleX_发射(uint64 key, uvec2 区间, vec3* point, vec3* dir, bool 是否激活, float32 抖动)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return {};

	uvec2 新添加区间 = {};

	MapBuffers(sim->g_buffers);

	uint64 gloOffset = 0;
	for (uint32 i = 区间.x; i < 区间.y; ++i) {
		sim->g_buffers->positions[i].x = point[gloOffset].x;
		sim->g_buffers->positions[i].y = point[gloOffset].y;
		sim->g_buffers->positions[i].z = point[gloOffset].z;
		//sim->g_buffers->positions[gloOffset].x = i * 0.5;
		//sim->g_buffers->positions[gloOffset].y = i * 0.5;
		//sim->g_buffers->positions[gloOffset].z = i * 0.5;
		sim->g_buffers->velocities[i] = Vec3( dir[gloOffset].x, dir[gloOffset].y, dir[gloOffset].z ) + RandomUnitVector() * 抖动;
		//sim->g_buffers->velocities[gloOffset] = { 0, 0, 0 };
		//sim->g_buffers->phases[gloOffset] = phase;
		if(是否激活) sim->g_buffers->activeIndices.push_back(i);

		++gloOffset;
	}

	UnmapBuffers(sim->g_buffers);

	return 新添加区间;
}







void f_NvFleX_set流体(uint64 key, vec3* point, float32* 质量, float32 速度, uvec2 区间, bool 是否激活, float32 抖动) {
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;

	f_基本粒子拷贝(sim, point, 质量, 速度, (NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid)), 区间, 抖动, 是否激活);

	sim->g_params.radius = 0.1;
	sim->g_params.dynamicFriction = 0.01f;
	sim->g_params.viscosity = 2.0f;
	sim->g_params.numIterations = 4;
	sim->g_params.vorticityConfinement = 40.0f;
	sim->g_params.fluidRestDistance = 0.1 * 0.55;
	sim->g_params.solidPressure = 0.f;
	sim->g_params.relaxationFactor = 0.0f;
	sim->g_params.cohesion = 0.02f;
	sim->g_params.collisionDistance = 0.01f;

	区间.y = sim->g_buffers->positions.size();
}

void f_NvFleX_set刚体(uint64 key, vec3* point, float32* 质量, vec4* 法线, float32 速度, uvec2 区间, uint32 ID, float32 刚性, float32 抖动) {
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;

	if (sim->g_buffers->rigidIndices.empty()) sim->g_buffers->rigidOffsets.push_back(0);
	f_基本粒子拷贝(sim, point, 质量, 速度, (NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid)), 区间, 抖动, true);

}









void f_NvFleX_取更新数据(uint64 key, std::vector<vec4>& point)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;



	MapBuffers(sim->g_buffers);

	uint32 num = sim->g_buffers->positions.size();
	point.resize(num);

#pragma omp parallel for
	for (int64 i = 0; i < num; ++i) {
		Vec4 pos = sim->g_buffers->positions[i];
		point[i].x = pos.x;
		point[i].y = pos.y;
		point[i].z = pos.z;
		point[i].w = 3.0;
	}

	UnmapBuffers(sim->g_buffers);
}

void f_NvFleX_取飞溅数据(uint64 key, std::vector<vec4>& point, std::vector<vec4>& dir)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;


	MapBuffers(sim->g_buffers);

	NvFlexGetDiffuseParticles(sim->g_solver, sim->g_buffers->diffusePositions.buffer, sim->g_buffers->diffuseVelocities.buffer, sim->g_buffers->diffuseCount.buffer);
	uint32 num = sim->g_buffers->diffuseCount[0];

	point.resize(num);
	auto* pr = point.data();

#pragma omp parallel for
	for (int64 i = 0; i < num; ++i) {
		Vec4 pos = sim->g_buffers->diffusePositions[i];
		point[i].x = pos.x;
		point[i].y = pos.y;
		point[i].z = pos.z;
		point[i].w = 3.0;
	}

	UnmapBuffers(sim->g_buffers);
	
}


void f_NvFleX_取变换数据(uint64 key, std::vector<vec4>& rot, std::vector<vec3>& loc)
{
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;

	MapBuffers(sim->g_buffers);

	if (sim->g_buffers->triangles.size())
		NvFlexGetDynamicTriangles(sim->g_solver, sim->g_buffers->triangles.buffer, sim->g_buffers->triangleNormals.buffer, sim->g_buffers->triangles.size() / 3);

	// readback rigid transforms
	if (sim->g_buffers->rigidOffsets.size()) {
		NvFlexGetRigids(sim->g_solver, NULL, NULL, NULL, NULL, NULL, NULL, NULL, sim->g_buffers->rigidRotations.buffer, sim->g_buffers->rigidTranslations.buffer);

		rot.resize(sim->g_buffers->rigidRotations.size());
		loc.resize(sim->g_buffers->rigidTranslations.size());
		memcpy(rot.data(), sim->g_buffers->rigidRotations.mappedPtr, sizeof(vec4) * rot.size());
		memcpy(loc.data(), sim->g_buffers->rigidTranslations.mappedPtr, sizeof(vec3) * loc.size());
	}

	UnmapBuffers(sim->g_buffers);
}

void f_NvFleX_取区间坐标数据(uint64 key, uvec2 r, std::vector<vec3>& point) {
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;


	MapBuffers(sim->g_buffers);

	uint32 num = sim->g_buffers->positions.size();
	uint32 offset = point.size();

	point.resize(offset + num);
#pragma omp parallel for
	for (int64 i = r.x; i < r.y; ++i, ++offset) {
		Vec4 pos = sim->g_buffers->positions[i];
		point[offset].x = pos.x;
		point[offset].y = pos.y;
		point[offset].z = pos.z;
	}

	UnmapBuffers(sim->g_buffers);
}

void f_NvFleX_get数据(uint64 key, std::vector<vec4>& point, std::vector<vec4>& 飞溅, std::vector<vec3>& 速度, std::vector<int32>& 激活) {
	S_解算参数* sim = nullptr;
	auto iter = g_解算器.find((S_解算参数*)key);
	if (iter != g_解算器.end()) sim = *iter;
	else return;

	MapBuffers(sim->g_buffers);

	int64 num = sim->g_buffers->positions.size();
	point.resize(num);
	飞溅.resize(num);
	速度.resize(num);
	激活.resize(num);

	vec4* p = point.data();
	vec4* d = 飞溅.data();
	vec3* v = 速度.data();
	int32* a = 激活.data();

	auto velocities = (Vec3*)(sim->g_buffers->velocities.mappedPtr);
	auto active = (int32*)(sim->g_buffers->activeIndices.mappedPtr);


	memcpy(p, sim->g_buffers->positions.mappedPtr, num * sizeof(Vec4));
	memcpy(v, sim->g_buffers->velocities.mappedPtr, num * sizeof(vec3));
	memcpy(p, sim->g_buffers->activeIndices.mappedPtr, num * sizeof(int32));

	num = sim->g_buffers->diffuseCount[0];
	memcpy(d, sim->g_buffers->diffusePositions.mappedPtr, num * sizeof(Vec4));

/*#pragma omp parallel for
	for (int64 i = 0; i < num; ++i) {
		Vec4 pos = sim->g_buffers->positions[i];
		point[i].x = pos.x;
		point[i].y = pos.y;
		point[i].z = pos.z;
		point[i].w = pos.w;

		v[i].x = velocities[i].x;
		v[i].y = velocities[i].y;
		v[i].z = velocities[i].z;

		a[i] = active[i];
	}*/

	UnmapBuffers(sim->g_buffers);
}











